package com.izhengyin.gateway.tracing;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.izhengyin.gateway.base.ApiManageService;
import com.izhengyin.gateway.base.StatisticsService;
import com.izhengyin.gateway.base.filters.RequestResolveFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Objects;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 网关链路追踪配置
 * @author zhengyin zhengyinit@outlook.com
 * Created on 2020-11-16 15:02
 */
@ConditionalOnProperty(name = "spring.application.gateway.tracing.enable", havingValue = "true", matchIfMissing = true)
@ConditionalOnBean(RequestResolveFilter.class)
@Slf4j
@Configuration
public class GatewayTracingConfiguration {

    public GatewayTracingConfiguration(){
    }

    @Bean
    public GlobalFilter gatewayZipkinFilter(
            TelemetryFactory telemetryFactory,
            ApiManageService apiManageService,
            StatisticsService statisticsService,
            TracingConfigUtils tracingConfigUtils
    ){
        return new GatewayTracingFilter(telemetryFactory,apiManageService,statisticsService,tracingConfigUtils);
    }

    @Bean
    public TelemetryFactory openTelemetryFactory(){
        return new TelemetryFactory();
    }

    /**
     * 接口采样配置
     * @return
     */
    @ConfigurationProperties(
            prefix = "trace-config"
    )
    @Bean("traceConfigProperties")
    @RefreshScope
    public Properties traceConfigProperties(){
        return new Properties();
    }

    @Bean("traceConfig")
    @RefreshScope
    public ConcurrentHashMap<String, Double> traceConfigs(@Qualifier("traceConfigProperties") Properties traceConfigProperties){
        Objects.requireNonNull(traceConfigProperties,"traceConfigProperties cannot be null!");
        ConcurrentHashMap<String,Double> configs = new ConcurrentHashMap<>(traceConfigProperties.size());
        traceConfigProperties.forEach((name,value) -> {
            try{
                configs.put(name.toString(),Double.parseDouble(value.toString().trim()));
            }catch (NumberFormatException e){
                log.error("set trace config {} error , {}",name,e.getMessage());
            }
        });
        log.info("traceConfigs {}", JSON.toJSONString(configs, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteDateUseDateFormat));
        return configs;
    }

    @Bean("traceConfigUtils")
    @RefreshScope
    public TracingConfigUtils traceConfigUtils(@Qualifier("traceConfig") ConcurrentHashMap<String, Double> traceConfig){
        return new TracingConfigUtils(traceConfig);
    }
}
